#include "factory.h"

int main(int argc,char** argv)
{
    if(argc!=3)
    {
        printf("/thread_pool_server IP PORT\n");
        return -1;
    }
    ARGS_CHECK(argc,3);
    int sfd;
    sfd=socket(AF_INET,SOCK_STREAM,0);//初始化一个网络描述符，对应了一个缓冲区
    ERROR_CHECK(sfd,-1,"socket");
    printf("sfd=%d\n",sfd);
    struct sockaddr_in ser_addr;
    bzero(&ser_addr,sizeof(ser_addr));//清空
    ser_addr.sin_family=AF_INET;//代表要进行ipv4通信
    ser_addr.sin_addr.s_addr=inet_addr(argv[1]);//把ip的点分十进制转为网络字节序
    ser_addr.sin_port=htons(atoi(argv[2]));//把端口转为网络字节序
    struct epoll_event evs[2];
    //epoll注册监控sfd,STDIN_FILENO
    int epfd=epoll_create(1);
    epoll_add(epfd,STDIN_FILENO);
    epoll_add(epfd,sfd);
    Factory_t f;//主数据结构
    int thread_num=THREAD_NUM;//子线程数量
    int capacity=CAPACITY;//队列容量
    factory_init(&f,thread_num,capacity);//线程池初始化
    factory_start(&f,thread_num);//启动线程池
    Client_State_t* pnew;
    train_state_t* ct;
    usraddr usr;
    bzero(&ct,sizeof(train_state_t));
    pQue_t pq=&f.que;//让一个队列指针指向队列
    char c_cmd[128]={0};
    char info[128]={0};
    //char usrname[20]={0};
    char *passwd;//明文密码
    int flag=0;//在输入用户名和密码时判断是否与服务器端连接的标志
    int ready_fd_num,i,j,ret,cn;
    char salt[512]={0};
    char *crpwd;
    int cor;
    while(1)
    {
        //用户输入账号密码，并传给服务器端进行密码验证,成功之后在进行命令的传
        printf("usrname :");
        scanf("%s",usr.usrA);//用户输入用户名
        passwd=getpass("Input a password(不会明文显示):");//用户输入一个明文密码
        printf("The passwd is:%s\n",passwd);
        if(!flag)
        {
            //客户端就要去连接服务器
            cn=connect(sfd,(struct sockaddr *)&ser_addr,sizeof(ser_addr));
            ERROR_CHECK(cn,-1,"connect");
            if(-1==cn)
            {
                printf("Connect fail!\n");
            }
            flag=1;
        }
        usr.data_len=sizeof(usr.usrA);
        printf("----\n");
        ret=send_n(sfd,&usr.data_len,sizeof(int));//发送用户名长度
        SELFFUNC_ERR_CHECK(ret,"send_n");
        ret=send_n(sfd,&usr.usrA,4+usr.data_len);
        SELFFUNC_ERR_CHECK(ret,"send_n");
        printf("----\n");
        if(!cn)//客户端与服务器端连接成功
        {
            int salt_len=sizeof(salt);
            ret=recv_n(sfd,&salt_len,sizeof(int));//接收salt长度
            SELFFUNC_ERR_CHECK(ret,"recv_n");
            ret=recv_n(sfd,salt,4+salt_len);//接收salt内容
            SELFFUNC_ERR_CHECK(ret,"recv_n");
            usr.data_len=sizeof(usr.pwd);
            crpwd = crypt(passwd,salt);//将用户的密码与salt加密得到一个与密码文件中密码进行对比的加密字符串
            sprintf(usr.pwd,"%s",crpwd);
            ret=send_n(sfd,&usr.data_len,sizeof(int));//发送加密字符串长度
            SELFFUNC_ERR_CHECK(ret,"send_n");
            ret=send_n(sfd,usr.pwd,4+usr.data_len);
            SELFFUNC_ERR_CHECK(ret,"send_n");//发送加密字符串内容
            //客户端接收服务器的密码确认信息，密码正确为0
            ret=recv_n(sfd,&cor,sizeof(int));//接收服务器端返回的密码验证情况，正确返回0
            SELFFUNC_ERR_CHECK(ret,"recv_n");
            if(!cor)//密码验证成功
            {
                command_options();
                while(1)
                {
                    ready_fd_num=epoll_wait(epfd,evs,2,-1);//等待描述符就绪，哪个描述符就绪，epoll就会返回
                    for(i=0;i<ready_fd_num;i++)
                    {
                        if(evs[i].data.fd==STDIN_FILENO)//标准输入可读
                        {
                            fflush(STDIN_FILENO);
                            bzero(&ct,sizeof(train_state_t));
                            scanf("%s %s",ct->cmd,ct->file_name);
                            ct->cmd_type = cmd_type_func(ct->cmd);
                            if (ct->cmd_type<1|| ct->cmd_type>6)
                            {
                                printf("Invalid input\n");
                                continue;
                            }
                            ct->data_len=sizeof(train_state_t);
                            ret=send_n(sfd,&ct->data_len,sizeof(int)); 
                            ERROR_CHECK(ret,-1,"send_n");
                            ret=send_n(sfd,&ct,4+ct->data_len);
                            ERROR_CHECK(ret,-1,"send_n");
                        }
                        if(evs[i].data.fd==sfd)//如果sfd可读
                        {
                            if(ct->cmd_type==LS||ct->cmd_type==CD||ct->cmd_type==REMOVE||ct->cmd_type==PWD)
                            {
                                int c_cmd_len;
                                bzero(info,sizeof(info));
                                ret=recv_n(sfd,&c_cmd_len,sizeof(int));//接收服务器端发送的火车头
                                ERROR_CHECK(ret,-1,"recv_n");
                                ret=recv_n(sfd,info,c_cmd_len);//接收服务器端发送的火车厢
                                ERROR_CHECK(ret,-1,"recv_n");
                                printf("%s\n",info);
                            }
                            else
                            {
                                printf("thread start!\n");
                                pnew=(Client_State_t*)calloc(1,sizeof(Client_State_t));//申请空间
                                //pnew放入队列
                                pnew->sfd=sfd;
                                pthread_mutex_lock(&pq->mutex);//加锁
                                que_set(pq,pnew);//放入队列
                                pthread_mutex_unlock(&pq->mutex);//解锁
                                pthread_cond_signal(&f.cond);//使条件成立
                            }
                        }    
                    }
                }
            }
            else{
                printf("The usrname or passwd is incorrect!\n");
            }
        }
        printf("Connect fail!\n");  
    }
    close(sfd);
    printf("---\n");
    return 0;
}